Blazor與其他前端框架一樣,是由一個一個元件(component)所組合而成的,每個元件都有各自的用途,將這些元件拼湊起來,就成了我們的SPA應用程式,所以我們時常會遇到元件需要互相傳遞資料的情況,一種常見的組合模式是巢狀元件,也就是一個元件內還包含另一個元件。
巢狀元件傳遞資料的方式大概如上圖
父元件要傳遞資料給子元件的作法,就是透過Parameter傳遞,子元件可以透過Paramter屬性取得資料。
子元件需要設定一個型別為EventCallback或EventCallback的Paramter屬性,這個屬性的主要用途,是讓子元件可以透過EventCallback的InvokeAsync方法,傳遞資料給父元件。而父元件這邊,則需要再新增一個callback method,來接收子元件資料並做後續處理。
接下來我們來做個Todolist來試試看吧,下圖是我們準備要做出的Todolist,外層的父元件顯示所有的Todo Item,並且可以新增Todo Item,而每一個子元件需要顯示單獨的Item和Delete按鈕,按下Delete後會傳遞Item index給父元件,父元件透過callback method接收item index後,進行刪除item動作。
我們先來看父元件的程式
@page "/Todo"
<div>
<table class="table table-hover">
<tr>
<th>待辦事項</th>
<th>刪除</th>
</tr>
@for (int i = 0; i < TodoList.Count; i++)
{
<Todo ItemName="@TodoList[i]" ItemIndex="@i" DeleteItem="@DeleteCallback" />
}
</table>
</div>
<div>
<label>New Todo:</label> <input type="text" @bind="newTodoItem" /> <button class="btn btn-primary" @onclick="Add">Add</button>
</div>
<br />
@code{
private string newTodoItem;
private List<string> TodoList;
protected override void OnInitialized()
{
TodoList = new List<string>()
{
"Buy Milk",
"Buy Apple"
};
}
void Add()
{
if (!string.IsNullOrEmpty(newTodoItem))
{
TodoList.Add(newTodoItem);
newTodoItem = "";
}
}
void DeleteCallback(int index)
{
TodoList.RemoveAt(index);
}
}
再來我們看子元件Todo.razor的部分。
<tr>
<td>@ItemName </td>
<td><button class="btn btn-danger btn-sm" @onclick="Delete">delete</button></td>
</tr>
@code {
[Parameter]
public string ItemName { get; set; }
[Parameter]
public int ItemIndex { get; set; }
[Parameter]
public EventCallback<int> DeleteItem { get; set; }
void Delete()
{
DeleteItem.InvokeAsync(ItemIndex);
}
}
@onclick=(() ⇒ DeleteItem.InvokeAsync(ItemIndex))
看看我們的TodoList吧